package com.ayz.gateway.assist.application;


import cn.hutool.core.util.StrUtil;
import com.ayz.gateway.assist.config.GatewayServiceProperties;
import com.ayz.gateway.assist.exception.GatewayContextStartException;
import com.ayz.gateway.assist.listener.AllocationApiDataChangeListener;
import com.ayz.gateway.common.constants.GatewayServiceData;
import com.ayz.gateway.common.notify.NotifyCenter;
import com.ayz.gateway.core.context.context.ApiGatewayContext;
import com.ayz.gateway.sdk.gatawayService.GatewayServiceSdk;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @ClassName GatewayApplicationListener
 * @Description TODO: 网关上下文启动的监听器
 * 监听到 ApplicationContextRefreshedEvent后完成 网关上下文的刷新
 * @Author 快乐的星球
 * @Date 2023/5/25 11:02
 * @Version 1.0
 **/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GatewayContextStartListener implements ApplicationListener<ContextRefreshedEvent>{

    private static final Logger LOG=Logger.getLogger(GatewayContextStartListener.class);

    public static String GATEWAY_ID_PREFIX="gateway";
    /**
     * 网关上下文
     */
    private ApiGatewayContext gatewayContext;
    /**
     * 网关服务的配置参数
     */
    private GatewayServiceProperties properties;
    /**
     * 网关服务的网络通信组件
     * 主要功能是: 网关服务与网关注册中心的所有通信行为全由当前类完成
     */
    private GatewayServiceSdk gatewayServiceSdk;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        LOG.info("容器刷新成功!启动向网关注册中心进行服务注册.......");
        prepareProperties(gatewayServiceSdk.getGatewayServiceData());
        /**
         * 这里要干以下几件事情
         * 1.完成网关通信组件的启动
         * 2.网关服务上下文的启动
         * 3.监听当前API网关服务分配的API信息发生变更事件
         *   完成监听器的注册
         */
        try {
            gatewayServiceSdk.start();
            LOG.info("网关服务上下文网络通信组件启动成功!");
            gatewayContext.start();
            LOG.info("网关服务上下文启动成功!");
            NotifyCenter.getINSTANCE().getEventMulticaster().addApplicationListener(new AllocationApiDataChangeListener(gatewayContext.getConfiguration()));
            LOG.info("注册业务组下网关API变更事件监听器!");
        } catch (Exception e) {
            LOG.error("网关服务上下文网络通信组件启动失败!");
            throw new GatewayContextStartException("网关服务上下文或者网关服务通信组件启动失败!");
        }
    }

    private void prepareProperties(GatewayServiceData gatewayServiceData){
        String gatewayId = gatewayServiceData.getGatewayId();
        if(StrUtil.isBlank(gatewayId)){
            String host = properties.getHost();
            if(StrUtil.isNotBlank(host)){
                gatewayId=GATEWAY_ID_PREFIX+host+":"+properties.getNetty().getPort();
                gatewayServiceData.setGatewayId(gatewayId);
                gatewayServiceData.setAddress(host+":"+properties.getNetty().getPort());
            }else {
                try {
                    String localIp = InetAddress.getLocalHost().getHostAddress();
                    int port = properties.getNetty().getPort();
                    gatewayId=GATEWAY_ID_PREFIX+localIp+"@"+port;
                    gatewayServiceData.setGatewayId(gatewayId);
                    gatewayServiceData.setAddress(localIp+":"+port);
                } catch (UnknownHostException e) {
                    LOG.error("获取本机IP地址失败,请检查原因或者自行指定参数{gatewayId}!",e);
                    throw new RuntimeException(e);
                }
            }
        }

    }
}
